package etf.hibernate;


import java.util.List;
import java.util.Random;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import etf.library.Address;
import etf.library.Employee;
import etf.library.IndexedAddress;

public class SimpleHibernate {

	SessionFactory sessions;
	Session session;
	Transaction tx;

	public SimpleHibernate() {
		// Create SessionFactory and Session object
		sessions = new Configuration().configure().buildSessionFactory();
		session = sessions.openSession();
		tx = null;
	}

	public long insert(int brojSlogova) {
		long elapsedTime = 0;
		try {
			tx = session.beginTransaction();

			long startTime = System.currentTimeMillis();
			for (int i = 0; i < brojSlogova; i++) {
				Address address = new Address("Splitska_" + i,i, "Sarajevo", 71000, "BiH");
				session.save(address);
			}
			tx.commit();
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}
		return elapsedTime;
	}
	
	public long indexedInsert(int brojSlogova) {
		long elapsedTime = 0;
		try {
			tx = session.beginTransaction();

			long startTime = System.currentTimeMillis();
			for (int i = 0; i < brojSlogova; i++) {
				IndexedAddress address = new IndexedAddress("Splitska_" + i,i, "Sarajevo", 71000, "BiH");
				session.save(address);
			}
			tx.commit();
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}
		return elapsedTime;
	}
	
	public long deleteAll(String className){
		long elapsedTime = 0;
		try {
			tx = session.beginTransaction();

			long startTime = System.currentTimeMillis();
			String hql = "delete from " + className;
			Query query = session.createQuery(hql);
			query.executeUpdate();
			tx.commit();
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}		
		
		return elapsedTime;
	}
	
	public long indexedDelete(int size){
		String hqlDelete = "delete IndexedAddress where houseNumber = :houseNumber";
		return deleteUtil(hqlDelete,size);
	}
	
	public long delete(int size){
		String hqlDelete = "delete Address where houseNumber = :houseNumber";
		return deleteUtil(hqlDelete,size);
	}
	
	private long deleteUtil(String hqlDelete,int size){
		long elapsedTime = 0;
		try {
			tx = session.beginTransaction();
			Query deleteQuery = session.createQuery(hqlDelete);
			long startTime = System.currentTimeMillis();
			deleteQuery.setInteger("houseNumber", getRandom(size));
			deleteQuery.executeUpdate();
			tx.commit();
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}		
		
		return elapsedTime;
	}
	
	public long query(int size){
		String hqlQuery = "from Address where houseNumber = :p";
		long elapsedTime = 0;
		try {
			tx = session.beginTransaction();
			Query query = session.createQuery(hqlQuery);
			long startTime = System.currentTimeMillis();
			query.setInteger("p", getRandom(size));
			List<Address> result = query.list();
			if (result.size()>0){
				Address a =  result.get(0);
				System.out.println(a.getStreet());
			}
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}		
		
		return elapsedTime;
	}
	
	public long indexedQueryInt(int size){
		long elapsedTime = 0;
		String hqlQuery = "from IndexedAddress where houseNumber = :p";
		try {
			tx = session.beginTransaction();
			Query query = session.createQuery(hqlQuery);
			long startTime = System.currentTimeMillis();
			query.setInteger("p", getRandom(size));
			List<IndexedAddress> result = query.list();
			if (result.size()>0){
				IndexedAddress a =  result.get(0);
				System.out.println(a.getStreet());
			}
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}		
		
		return elapsedTime;
	}
	
	public long indexedQueryString (int size){
		long elapsedTime = 0;
		String hqlQuery = "from IndexedAddress where street = :p";
		try {
			tx = session.beginTransaction();
			Query query = session.createQuery(hqlQuery);
			long startTime = System.currentTimeMillis();
			query.setString("p", "Splitska_" + getRandom(size));
			List<IndexedAddress> result = query.list();
			if (result.size()>0){
				IndexedAddress a =  result.get(0);
				System.out.println(a.getStreet());
			}
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}		
		
		return elapsedTime;
	}
	
	public long update (int size){
		long elapsedTime = 0;
		String hqlQuery = "from IndexedAddress where houseNumber = :houseNumber";
		try {
			
			long startTime = System.currentTimeMillis();
			tx = session.beginTransaction();
			Query query = session.createQuery(hqlQuery);
			query.setInteger("houseNumber", getRandom(size));
			List<IndexedAddress> result = query.list();
			if (result.size()>0){
				IndexedAddress a =  result.get(0);
				a.setCity("New_city");
				session.save(a);
			}
			tx.commit();
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;

			tx = null;
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		}		
		
		return elapsedTime;
	}
	
	
	private int getRandom(int max){
		Random r = new Random();
        return r.nextInt(max); 
	}
	
	public void closeSession() {
		session.close();
	}
}
